

/**
 * 双向加密中间件
 */

module.exports = () => {

    let specialKey = 'kjhsagyw@#@!lnln';

    function isNull(data) {
        if (typeof data === 'undefined') return true;
        if (data == NaN) return true;
        if (data === '') return true;
    }

    function isJson(str) {
        try {
            JSON.parse(str);
            return true;
        } catch (error) {
            return false;
        }
    }

    /**
     * 将接口返回数据进行打包加密
     * @param {Object} ctx 接口上下文
     * @returns 
     */
    function extrun(ctx) {
        if (isNull(ctx.body)) return '';
        let body = JSON.stringify(ctx.body);
        let timeData = parseInt(Date.now() / 1000);//当前时间戳
        let md5Body = ctx.fun.md5(timeData + body + specialKey);
        let combine = { data: ctx.body, verify: md5Body, time: timeData };
        return ctx.fun.encrypt(combine);
    }

    /**
     * 接收req.body的数据解密效验md5 并返回数据
     * @param {Object} ctx 接口上下文
     */
    function decget(ctx) {
        let combine = null;
        if (ctx.request.method == 'POST' && isNull(ctx.request.body)) {
            ctx._throw(404, 'data error');
        } else if((ctx.request.method != 'POST' && isNull(ctx.request.body))){
            return {};
        }
        if (typeof ctx.request.body !== 'string') return {};
        try {
            combine = ctx.fun.decrypt(ctx.request.body);
        } catch (error) {
            ctx._throw(404, 'data error');
        }
        if (!isJson(combine)) {
            ctx._throw(404, 'data error');
        }
        combine = JSON.parse(combine);//转对象
        let md5Body = ctx.fun.md5(combine.time + JSON.stringify(combine.data) + specialKey);
        if (combine.verify !== md5Body) {
            ctx._throw(4042,'data exception');
        }
        return combine.data;
    }

    return async (ctx, next) => {
        ctx.request.body = decget(ctx);
        await next();
        ctx.__isEncrypt = ctx.__isEncrypt ?? true;
        if(ctx.__isEncrypt){
            ctx.body = extrun(ctx);
        }
        ctx.__isEncrypt = true;
    };
}